/**
 * @author [迷途小羔羊]
 * 创建于：2018-1-25
 * 最后修改：2018-1-25
 * contact:[qq:229449388,mail:229449388@qq.com]
 */
namespace GYLite
{

	export class MathUtil
	{
		private static sin_map:any = {};
		private static cos_map:any = {};
		public static DEG_TO_RAD:number = Math.PI / 180;
		// public static temp1 = new Laya.Vector3;
		// public static temp2 = new Laya.Vector3;
		public static tempPt = new egret.Point;
		private static _instance:MathUtil = new MathUtil;
		constructor()
		{
			for (var numberUtils_i:number = 0; numberUtils_i < 360; numberUtils_i++) {
				MathUtil.sin_map[numberUtils_i] = Math.sin(numberUtils_i * MathUtil.DEG_TO_RAD);
				MathUtil.cos_map[numberUtils_i] = Math.cos(numberUtils_i * MathUtil.DEG_TO_RAD);
			}
			MathUtil.sin_map[90] = 1;
			MathUtil.cos_map[90] = 0;
			MathUtil.sin_map[180] = 0;
			MathUtil.cos_map[180] = -1;
			MathUtil.sin_map[270] = -1;
			MathUtil.cos_map[270] = 0;
		}
		/**计算过一点做平行线的另外一点坐标
		 * @param p1x 直线上的A点X坐标
		 * @param p1y 直线上的A点Y坐标
		 * @param p2x 直线上的B点X坐标
		 * @param p2y 直线上的B点Y坐标
		 * @param p3x 平行线上的C点X坐标
		 * @param p3y 平行线上的C点Y坐标
		 * @param val 乘量
		 * @param 返回的平行点P，赋值null则创建新的
		 * @return 返回平行点P
		 * */
		public static calParallelPoint(p1x:number,p1y:number,p2x:number,p2y:number,p3x:number,p3y:number,val:number = 0.5,p:egret.Point=null):egret.Point
		{			
			if(p == null)
				p = new egret.Point;
			p.x = p3x;
			p.y = p3y;
			p.x += (p2x - p1x)*val;
			p.y += (p2y - p1y)*val;
			return p;
		}
		/**创建一个等边多边形
		 * @param r 半径
		 * @param num 边数量
		*/
		public static calPolygonByRadius(r:number,num:number=3,startDegree:number=0):number[]
		{
			let result:number[] = [];
			let i:number,len:number,step:number,startAgl:number,agl:number,x:number,y:number;
			if(num < 3)
				num = 3;
			r = Number(r);
			if(r != r)
				r = 100;
			len = num;
			startAgl = startDegree * MathConst.ROTATION_ANGLE;
			step = MathConst.DOUBLE_PI / num;
			for(i=0;i<len;++i)
			{
				agl = startAgl + i*step;
				x = Math.cos(agl)*r|0;
				y = Math.sin(agl)*r|0;				
				result.push(x,y);
			}
			return result;
		}
		/**计算多边形最大外接圆半径(凸多边形)
		 * @param arr 轮廓数组
		 * @param minDis 最小范围
		 * @param maxDis 最大范围
		 * @param result 当前值
		*/
		public static calMaxRadiusInShape(arr:number[],minDis:number=32, maxDis:number=9999999,result:number=32):number
		{
			let i:number,len:number;
			let ax:number,ay:number,dis:number;
			let pt:egret.Point;
			minDis *= minDis;
			maxDis *= maxDis;			
			result *= result;
			len = arr.length;
			for(i=0;i<len;i+=2)
			{
				ax = arr[i];
				ay = arr[i+1];				
				dis = PositionUtil.calculateDistance2(ax,ay,0,0);
				if(dis < minDis)
					continue;
				if(dis > maxDis)
					continue;
				result = Math.max(dis, result);
			}
			return Math.pow(result,0.5);
		}
		/**计算多边形最小内切圆半径
		 * @param arr 轮廓数组
		 * @param minDis 最小范围
		 * @param maxDis 最大范围
		 * @param result 当前值
		*/
		public static calMinRadiusInShape(arr:number[],minDis:number=32,maxDis:number=9999999,result:number=Number.MAX_VALUE):number
		{
			let i:number,len:number;
			let ax:number,ay:number,bx:number,by:number;
			let pt:egret.Point;
			let dis:number;
			minDis *= minDis;
			maxDis *= maxDis;
			result *= result;
			len = arr.length;
			for(i=0;i<len;i+=2)
			{
				if(i == len - 2)
				{
					ax = arr[i];
					ay = arr[i+1];
					bx = arr[0];
					by = arr[1];
				}
				else
				{
					ax = arr[i];
					ay = arr[i+1];
					bx = arr[i+2];
					by = arr[i+3];
				}				
				pt = MathUtil.calVerticalPoint(ax,ay,bx,by,0,0);
				dis = pt.x*pt.x+pt.y*pt.y;
				if(dis < minDis)
					continue;
				if(dis > maxDis)
					continue;
				result = Math.min(dis,result);
			}
			return Math.pow(result,0.5);
		}
		/**计算多边形最小边框*/
		public static calMaxRect(arr:number[]):number[]
		{
			let i:number,len:number,minX:number,maxX:number,minY:number,maxY:number;			
			let x:number,y:number;
			minX = minY = Number.MAX_VALUE;
			maxX = maxY = Number.MIN_VALUE;			
			len = arr.length;
			for(i=0;i<len;i+=2)
			{
				x = arr[i];
				y = arr[i+1];
				if(minX > x)
					minX = x;
				if(maxX < x)
					maxX = x;
				if(minY > y)
					minY = y;
				if(maxY < y)
					maxY = y;				
			}
			return [minX,minY,maxX,maxY];
		}
		/**计算过一点做垂线的垂点坐标
		 * @param p1x 直线上的A点X坐标
		 * @param p1y 直线上的A点Y坐标
		 * @param p2x 直线上的B点X坐标
		 * @param p2y 直线上的B点Y坐标
		 * @param p3x 垂线上的C点X坐标
		 * @param p3y 垂线上的C点Y坐标
		 * @param 返回的垂点P，赋值null则创建新的
		 * @return 返回垂点P
		 * */
		public static calVerticalPoint(p1x:number,p1y:number,p2x:number,p2y:number,p3x:number,p3y:number,p:egret.Point=null):egret.Point
		{
			if(p == null)
				p = new egret.Point;
			p.x = p1x;
			p.y = p1y;
			var a:number,b:number,c:number;
			var tX:number,tY:number;
			var x0:number,y0:number;
			x0 = p3x;
			y0 = p3y;
			a = p1y - p2y;
			b = p2x - p1x;
			c = p2x * (p2y - p1y) - p2y * (p2x-p1x);
			tX = (b*b*x0-a*b*y0-a*c)/(a*a+b*b);
			tY = (a*a*y0-a*b*x0-b*c)/(a*a+b*b);
			p.x = tX;
			p.y = tY;
			return p;
		}
		
		/**计算两直线交点
		 * @param p1StartX 直线A的起点x
		 * @param p1StartY 直线A的起点y
		 * @param p1EndX 直线A的终点x
		 * @param p1EndY 直线A的终点y
		 * @param p2StartX 直线B的起点x
		 * @param p2StartY 直线B的起点y
		 * @param p2EndX 直线B的终点x
		 * @param p2EndY 直线B的终点y
		 * @param p 接受返回的交点Point对象，传null则创建新的Point对象
		 * @param return 返回交点p 不相交则返回null
		*/
		public static calCrossPoint(p1StartX:number,p1StartY:number,p1EndX:number,p1EndY:number,p2StartX:number,p2StartY:number,p2EndX:number,p2EndY:number,p:egret.Point=null,segment:boolean=false):egret.Point
		{
			if(p == null)
				p = new egret.Point;
			if (p1StartX == p1EndX)
			{
				if (p2StartX == p2EndX)
				{
					// Log.writeLog("平行线");
					p = null;
				}
				else
				{
					p.x = p1StartX;
					p.y = p2StartY+(p1StartX-p2StartX)/(p2EndX-p2StartX)*(p2EndY-p2StartY);
				}
			}
			else if (p2StartX == p2EndX)
			{
				p.x = p2StartX;
				p.y = p1StartY+(p2StartX-p1StartX)/(p1EndX-p1StartX)*(p1EndY-p1StartY);
			}
			else
			{
				var K1:number = (p1StartY-p1EndY)/(p1StartX-p1EndX);
				var K2:number = (p2StartY-p2EndY)/(p2StartX-p2EndX);
				if (K1 == K2)
				{
					// Log.writeLog("平行线");
					p = null;
				}
				else
				{
					var B1:number = (p1StartX*p1EndY-p1StartY*p1EndX)/(p1StartX-p1EndX);
					var B2:number = (p2StartX*p2EndY-p2StartY*p2EndX)/(p2StartX-p2EndX);
					p.x = (B2 - B1) / (K1 - K2);
					p.y = K1 * p.x + B1;
				}
			}
			if(segment && p)
			{
				let tiny:number;
				tiny = NumberUtil.TINY_NUMBER_01;
				if(p1StartX <= p1EndX && (p1StartX - p.x > tiny || p.x - p1EndX > tiny) || p1StartX > p1EndX && (p.x - p1StartX > tiny || p1EndX - p.x > tiny))
					return null;
				if(p1StartY <= p1EndY && (p1StartY - p.y > tiny || p.y - p1EndY > tiny) || p1StartY > p1EndY && (p.y - p1StartY > tiny || p1EndY - p.y > tiny))
					return null;
				if(p2StartX <= p2EndX && (p2StartX - p.x > tiny || p.x - p2EndX > tiny) || p2StartX > p2EndX && (p.x - p2StartX > tiny || p2EndX - p.x > tiny))
					return null;
				if(p2StartY <= p2EndY && (p2StartY - p.y > tiny || p.y - p2EndY > tiny) || p2StartY > p2EndY && (p.y - p2StartY > tiny || p2EndY - p.y > tiny))
					return null;				
			}
			return p;
		}
		/**计算线段上指定长度的点的坐标
		 * @param p1x 起点x
		 * @param p1y 起点y
		 * @param p2x 终点x
		 * @param p2y 终点y
		 * @param len 长度
		 * @param angle 偏移角度
		 * */
		public static calLinePoint(p1x:number,p1y:number,p2x:number,p2y:number,len:number= 1,angle:number=0):egret.Point
		{
			var agl:number;
			if(p2y == p1y)
			{
				agl = p2x > p1x?MathConst.DOUBLE_PI:Math.PI;
			}
			else if(p2x == p1x)
			{
				agl = p2y > p1y?MathConst.HALF_PI:Math.PI*1.5;
			}
			else
			{
				agl = Math.atan2(p2y - p1y,p2x - p1x);
			}
			var tP:egret.Point = MathUtil.polar(len,agl + angle);
			tP.x += p1x;
			tP.y += p1y;
			return tP;
		}
		public static polar(r:number,angle:number,result:egret.Point=null):egret.Point
		{			
			result = result || new egret.Point;
			result.x = Math.cos(angle)*r;
			result.y = Math.sin(angle)*r;
			return result;
		}
		/**计算出多边形面积
		 * @param shapeArr 图形描点
		 * @param hasDirect 面积是否有向，默认false，面积小于0 顶点逆时针 大于0 顶点顺时针 等于0  (注意2d坐标系是y轴翻转的，所以图形的顶点顺序应该跟数学坐标系计算相反)
		*/
		public static calPolygonArea(shapeArr:number[],hasDirect:boolean=false):number
		{			
			let i:number,len:number;
			let sum:number=0;
			len = shapeArr.length;			
			if(len < 6)
				return sum;
			for(i=0;i<len;i+=2){
				if(i == len - 2)
					sum += MathUtil.calTriangleArea(0,0,shapeArr[i],shapeArr[i + 1],shapeArr[0],shapeArr[1],true);
				else
					sum += MathUtil.calTriangleArea(0,0,shapeArr[i],shapeArr[i+1],shapeArr[i+2],shapeArr[i+3],true);
			}
			return hasDirect?sum:(sum < 0?-sum:sum);
		}
		/**计算三角形面积*/
		public static calTriangleArea(x1 :number,y1 :number,x2 :number,y2 :number,x3 :number,y3 :number,hasDirect:boolean=false):number
		{
			let sum:number = (x2-x1)*(y3-y2)-(y2-y1)*(x3-x2);
			return hasDirect?sum:(sum < 0?-sum:sum);
		}
		/**快速算出角度value的sin值(近似值)
		 * @param value 角度 注意此参数为角度
		*/
		public static sin(value:number):number
		{
			var valueFloor:number,valueCeil:number;			
			var resultFloor:number,resultCeil:number;
			valueFloor = Math.floor(value);
			valueCeil = valueFloor + 1;
			if (valueFloor == value) 
				return MathUtil.sinInt(valueFloor);									
			resultFloor = MathUtil.sinInt(valueFloor);
			resultCeil = MathUtil.sinInt(valueCeil);
			return (value - valueFloor) * resultCeil + (valueCeil - value) * resultFloor;
		}
		/**快速算出整数角度的sin值
		 * @param value 角度 注意此参数为角度
		*/
		public static sinInt(value:number):number
		{
			value = value = MathUtil.clampRotaion(value);
			return MathUtil.sin_map[value];
		}
		/**快速算出角度value的cos值(近似值)
		 * @param value 角度 注意此参数为角度
		*/
		public static cos(value:number):number
		{
			var valueFloor:number,valueCeil:number;			
			var resultFloor:number,resultCeil:number;
			valueFloor = Math.floor(value);
			valueCeil = valueFloor + 1;
			if (valueFloor == value) 
				return MathUtil.cosInt(valueFloor);									
			resultFloor = MathUtil.cosInt(valueFloor);
			resultCeil = MathUtil.cosInt(valueCeil);
			return (value - valueFloor) * resultCeil + (valueCeil - value) * resultFloor;
		}
		/**快速算出整数角度的cos值
		 * @param value 角度 注意此参数为角度
		*/
		public static cosInt(value:number):number
		{
			value = MathUtil.clampRotaion(value);
			return MathUtil.cos_map[value];
		}
		/**角度0-2PI内取模*/
		public static clampAngle(value:number):number {
			value %= MathConst.DOUBLE_PI;
			if (value < 0) 
				value += MathConst.DOUBLE_PI;			
			return value;
		}
		/**角度0-2PI内取模*/
		public static clampRotaion(value:number):number {
			value = value % 360;
			if (value < 0) 
				value += 360;			
			return value;
		}

		/**点集排序，作用是排序后，按顺序连线可以形成不错位的多边形
		 * @param vPoints 顶点数组[x1,y1,x2,y2……]
		 * @param clockwise 是否顺时针 默认true
		*/
		public static clockwiseSortPoints(vPoints:number[],clockwise:boolean=true)
		{
			//计算重心
			let centerX:number,centerY:number;
			let x:number = 0,y:number = 0;
			let i:number,j:number,len:number,len2:number;
			let ax:number,bx:number,ay:number,by:number;
			let wise:number;
			let angleA:number,angleB:number;
			let flag:boolean;
			len = vPoints.length;
			for (i = 0;i < len;i+=2)
			{
				x += vPoints[i];
				y += vPoints[i+1];
			}
			len/=2;
			centerX = x/len;
			centerY = y/len;
			
			len = vPoints.length;
			//冒泡排序
			for(i = 0;i < len - 2;i+=2)
			{
				len2 = len - i - 2;
				for (j = 0;j < len2;j+=2)
				{
					ax = vPoints[j];
					ay = vPoints[j+1];

					bx = vPoints[j+2];
					by = vPoints[j+3];					
					angleA = MathUtil.calAngle(centerX,centerY,ax,ay);
					angleA = MathUtil.clampAngle(angleA);
					angleB = MathUtil.calAngle(centerX,centerY,bx,by);
					angleB = MathUtil.clampAngle(angleB);
					flag = angleA > angleB;
					
					if (flag)
					{						
						vPoints[j] = bx;
						vPoints[j + 1] = by;

						vPoints[j + 2] = ax;
						vPoints[j + 3] = ay;
					}
				}
			}
		}
		/**计算多边形交集
		 * @param poly1 多边形顶点数组1 [x1,y1,x2,y2……]
		 * @param poly2 多边形顶点数组2 [x1,y1,x2,y2……]
		 * @param result 存放结果的顶点数组 [x1,y1,x2,y2……]
		*/
		public static polygonClip(poly1:number[],poly2:number[], result:number[]=null):boolean
		{
			if(result == null)
				result = [];
			if (poly1.length < 6 || poly1.length%2 !=0 || poly2.length < 6 || poly2.length%2 !=0)
			{
				return false;
			}
			
			let x:number,y:number;
			let i:number,j:number,len:number,len2:number;
			let poly1_next_idx:number,poly2_next_idx:number;
			len = poly1.length;
			len2 = poly2.length;
			//计算多边形交点
			for (i = 0;i < len;i+=2)
			{
				poly1_next_idx = (i + 2) % len;
				for (j = 0;j < len2;j+=2)
				{
					poly2_next_idx = (j + 2) % len2;
					if (MathUtil.calCrossPoint(poly1[i],poly1[i+1],poly1[poly1_next_idx],poly1[poly1_next_idx+1],poly2[j],poly2[j+1],poly2[poly2_next_idx],poly2[poly2_next_idx+1],MathUtil.tempPt,true))
					{						
						result.push(MathUtil.tempPt.x,MathUtil.tempPt.y);
					}
				}
			}

			//计算多边形内部点
			for(i = 0;i < len;i+=2)
			{
				x = poly1[i];
				y = poly1[i+1];				
				if (PositionUtil.isPointInShape(x,y,poly2))				
					result.push(x,y);				
			}
			for (i = 0;i < len2;i+=2)
			{
				x = poly2[i];
				y = poly2[i+1];
				if (PositionUtil.isPointInShape(x,y,poly1))				
					result.push(x,y);				
			}
			//剔除重复顶点
			i = result.length - 2;
			len = 2;
			for(;i > 1;)
			{	
				x = result[i];
				y = result[i+1];
				for (j = i - 2;j > -1;j-=2)
				{
					if(NumberUtil.isNumberEqual(result[j], x) && NumberUtil.isNumberEqual(result[j+1],y))
						result.splice(j,2);
				}
				len += 2;
				i = result.length - len;
			}

			if(result.length < 6)
				return false;

			//点集排序
			MathUtil.clockwiseSortPoints(result);
			return true;
		}
		public static indexOfPoint(arr:number[], x:number, y:number):number
		{
			let i:number,len:number;
			len = arr.length;
			for (i = 0;i < len;i+=2)
			{
				if(arr[i] == x && arr[i+1] == y)				
					return i;				
			}
			return -1;
		}
		/**通过点积比较a和b的距离重心center的向量大小*/
		public static pointCmp(ax:number,ay:number,bx:number,by:number,centerX:number,centerY:number)
		{
			if (ax >= 0 && bx < 0)
				return true;
			if (ax == 0 && bx == 0)
				return ay > by;
			//向量OA和向量OB的叉积
			let det:number = (ax - centerX) * (by - centerY) - (bx - centerX) * (ay - centerY);
			if (det < 0)
				return true;
			if (det > 0)
				return false;
			//向量OA和向量OB共线，以距离判断大小
			let d1:number = (ax - centerX) * (ax - centerX) + (ay - centerY) * (ay - centerY);
			let d2:number = (bx - centerX) * (bx - centerX) + (by - centerY) * (by - centerY);
			return d1 > d2;
		}
		/**点积*/
		public static dot(vx1:number,vy1:number,vx2:number,vy2:number):number
		{
			return vx1*vx2 + vy1*vy2;
		}
		/**叉积*/
		public static cross(vx1:number,vy1:number,vx2:number,vy2:number):number
		{
			return vx1*vy2 - vx2*vy1;
		}
		/**3d点积*/
		public static d3Dot(vx1:number,vy1:number,vz1:number,vx2:number,vy2:number,vz2:number):number
		{
			return vx1*vx2 + vy1*vy2 + vz1*vz2;
		}
		/**3d叉积*/
		public static d3Cross(vx1:number,vy1:number,vz1:number,vx2:number,vy2:number,vz2:number,result:GYLite.Vector3=null):GYLite.Vector3
		{			
			result = result || new GYLite.Vector3;
			result.x = vy1*vz2 - vy2*vz1;
			result.y = vx1*vz2 - vx2*vz1;
			result.z = vx1*vy2 - vx2*vy1;
			return result;
		}
		/**求3个点所在的面的法向量*/
		// public static normalVector(a:Laya.Vector3,b:Laya.Vector3,c:Laya.Vector3,result:Laya.Vector3=null):Laya.Vector3
		// {
		// 	let v1:Laya.Vector3;
		// 	let v2:Laya.Vector3;
		// 	v1 = MathUtil.temp1;
		// 	v2 = MathUtil.temp2;
		// 	v1.reset(a.x - b.x,a.y-b.y,a.z-b.z);
		// 	v2.reset(a.x - c.x,a.y-c.y,a.z-c.z);
		// 	return MathUtil.d3Cross(v1.x,v1.y,v1.z,v2.x,v2.y,v2.z,result);			
		// }
		/**求射线在平面上相交的一点
		 * @param 射线的近点a
		 * @param 射线的远点b
		 * @param 平面上的一点 pt
		 * @param 平面的法向量 n 求3个点所在屏幕的法向量请使用接口normalVector
		 * **/
		public static rayPoint(a:GYLite.Vector3,b:GYLite.Vector3,pt:GYLite.Vector3,n:GYLite.Vector3,result:GYLite.Vector3 = null):GYLite.Vector3
		{
			let t:number,x:number,y:number,z:number;
			result = result || new GYLite.Vector3;
			// let c:Laya.Vector3;			
			// result.x = (b.x - a.x)*t;
			// result.y = (b.y - a.y)*t;
			// result.z = (b.z - a.z)*t;
			// c.x = result.x - pt.x;
			// c.y = result.y - pt.y;
			// c.z = result.z - pt.z;
			// ((b.x - a.x)*t - pt.x)*n.x + ((b.y - a.y)*t - pt.y)*n.y + ((b.z - a.z)*t - pt.z)*n.z == 0;
			// (b.x - a.x)*n.x*t-pt.x*n.x + (b.y - a.y)*n.y*t - pt.y*n.y + (b.z - a.z)*n.z*t - pt.z*n.z == 0;
			// ((b.x - a.x)*n.x+(b.y - a.y)*n.y + (b.z - a.z)*n.z)*t-pt.x*n.x - pt.y*n.y - pt.z*n.z==0;
			t = (pt.x*n.x + pt.y*n.y + pt.z*n.z)/((b.x - a.x)*n.x+(b.y - a.y)*n.y + (b.z - a.z)*n.z);
			y = (b.y - a.y)*t;
			x = (b.x - a.x)*t;
			z = (b.z - a.z)*t;
			result.reset(x,y,z);
			return result;
		}
		/**计算直线ab的夹角(或者向量[bx - ax,by - ay])*/
		public static calAngle(ax:number,ay:number,bx:number,by:number):number
		{
			if(ay == by)
				return bx > ax?0:Math.PI;
			if(ax == bx)
				return by > ay?MathConst.HALF_PI:-MathConst.HALF_PI;
			return Math.atan2(by - ay,bx - ax);
		}
		/**计算向量v1和v2的夹角*/
		public static calVecAngle(v1x:number,v1y:number,v2x:number,v2y:number):number
		{
			let aglA:number,aglB:number;
			aglA = MathUtil.calAngle(0,0,v1x,v1y);
			aglB = MathUtil.calAngle(0,0,v2x,v2y);
			return MathUtil.clampAngle(aglA - aglB);
		}
		/**根据权重随机获取，例如权重[3,3,4]，总和10，每个区间分别[0.3,0.6,1]，返回随机数小于的对应值索引*/
		public static randomGet(arr:number[]):number
		{
			let i:number,len:number;
			let all:number= 0;
			let cur:number=0;
			len = arr.length;
			for(i=0;i<len;++i)
			{
				all += arr[i];
			}
			let rnd:number = Math.random();
			len = arr.length;
			for(i=0;i<len;++i)
			{				
				cur += arr[i]/all;				
				if(rnd <= cur)
					return i;				
			}
			return 0;
		}

		/**计算撞墙后延墙壁的偏转角度
		 * @param vecX 墙体向量x
		 * @param vecY 墙体向量y
		 * @param vx 移动向量x
		 * @param vy 移动向量y
		 * @param agl 移动角度
		 **/
		 public static calDeflectionAngle(vecX:number,vecY:number,vx:number,vy:number):number
		 {			
			 let agl2:number,agl3:number;			
			 let dot:number,cross:number;			 	
			 let deflectionAngle:number;
			 deflectionAngle = 0;
			 dot = MathUtil.dot(vecX, vecY, vx, vy);
			 agl2 = Math.abs(Math.acos(dot/Math.pow(vx*vx + vy*vy, 0.5)/Math.pow(vecX*vecX + vecY*vecY, 0.5)))
			 if(agl2 != 0)
			 {					
				 cross = MathUtil.cross(vx,vy,vecX,vecY);
				 if(agl2 < MathConst.HALF_PI)
				 {
					 deflectionAngle = cross > 0?agl2:-agl2;					
				 }
				 else
				 {
					 agl3 = Math.PI - agl2;
					 deflectionAngle = cross > 0?-agl3:agl3;					
				 }				 
			 }
			 return deflectionAngle;
		 }
		 /**取区间限制值**/
		 public static clamp(value:number,min:number,max:number):number
		 {
			return Math.max(Math.min(value, max), min);
		 }
	}
	export class MathPoint
	{
		public x:number;
		public y:number;
		public k:number;
		public hash:number;
		constructor(x:number=0,y:number=0)
		{
			let s = this;
			s.x = x;
			s.y = y;
			s.hash = (y << 15) + x;
			s.k = y/x;
		}
	}
}